home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK1.toast / Development Kits (Disc 1) / QuickTime / Programming Stuff / Sample Code / Music Architecture / Mixed Bag / •QTMusic Sample Sequencer / SequencerTest Realtime.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-09  |  5.9 KB  |  334 lines  |  [TEXT/KAHL]

  1. /*
  2.  * file: SequencerTest Realtime.c
  3.  *
  4.  *
  5.  */
  6.  
  7.  
  8. /*--------------------------
  9.     Inclusions
  10. --------------------------*/
  11.  
  12. #include <QuickDraw.h>
  13. #include <Windows.h>
  14. #include <Memory.h>
  15. #include <Packages.h>
  16.  
  17. #include "BigEasy2.h"
  18. #include "BigEasyTextish.h"
  19. #include "BigEasyGrafish.h"
  20. #include "BigEasyDialogs.h"
  21.  
  22. #include "SequencerTest.h"
  23. #include "SequencerTest Realtime.h"
  24.  
  25. #include "Event Priority Queue.h"
  26.  
  27. /*--------------------------
  28.     Local Prototypes
  29. --------------------------*/
  30.  
  31. static void DelayXUnits(long x, long units);
  32.  
  33. static short GetPipDuration(ScorePart *sp,short x,short y);
  34.  
  35. static void PrerollDoc(TDoc *d);
  36.  
  37. /*--------------------------
  38.     The Bronx Zoo
  39. --------------------------*/
  40.  
  41.  
  42. void PlayScorePartBeat(ScorePart *sp, NoteChannel nc, short beat)
  43.     {
  44.     unsigned long thisMask,lastMask;
  45.     short thisElementH,lastElementH;
  46.     short elementV;
  47.     Boolean thisPip,lastPip;
  48.     ComponentResult thisError;
  49.  
  50.     thisMask = 1L << (beat & 31);
  51.     thisElementH = beat / 32;
  52.  
  53.     lastMask = 1L << (( (beat + kScoreLength - 1) % kScoreLength) & 31);
  54.     lastElementH = ( (beat + kScoreLength - 1) % kScoreLength) / 32;
  55.  
  56.     for(elementV = 0; elementV < kScoreHeight; elementV++)
  57.         {
  58.         if(beat == kScoreLength)
  59.             thisPip = 0;
  60.         else
  61.             thisPip = 0 != (sp->score[elementV][thisElementH] & thisMask);
  62.  
  63.         if(beat == 0)
  64.             lastPip = 0;
  65.         else
  66.             lastPip = 0 != (sp->score[elementV][lastElementH] & lastMask);
  67.  
  68.         if(thisPip && !lastPip)
  69.             {
  70.             thisError = NAPlayNote(g.na,nc,kNoteRangeHigh - elementV, 64);
  71.             ShowError(thisError);
  72.             }
  73.         else if(lastPip && !thisPip)
  74.             {
  75.             thisError = NAPlayNote(g.na,nc,kNoteRangeHigh - elementV, 0);
  76.             ShowError(thisError);
  77.             }
  78.         }
  79.     }
  80.  
  81.  
  82. void PrerollDoc(TDoc *d)
  83.     {
  84.     short j;
  85.     ComponentResult thisError;
  86.  
  87. #ifdef separateNoteChannel
  88.     for(j = 0; j<kScoreParts; j++)
  89.         {
  90.         thisError = NAPrerollNoteChannel(g.na,d->noteChannel[j]);
  91.         ShowError(thisError);
  92.         }
  93.  
  94. #endif
  95.     thisError = TunePreroll(d->tp);
  96.     ShowError(thisError);
  97.     }
  98.  
  99. void PlayDocOnce(TDoc *d)
  100.     {
  101.     short beat,j;
  102.     long dummy;
  103.     Boolean oldEngage,newEngage;
  104.     ComponentResult thisError;
  105.  
  106.     PrerollDoc(d);
  107.     oldEngage = true;
  108.  
  109.     for(beat = 0; beat < kScoreLength; beat ++)
  110.         {
  111.         newEngage = !Button();
  112.         if(newEngage != oldEngage)
  113.             {
  114.             if(newEngage)
  115.                 for(j = 0; j < kScoreParts; j++)
  116.                     {
  117.                     thisError = NAEngageNoteChannel(g.na,d->noteChannel[j]);
  118.                     ShowError(thisError);
  119.                     }
  120.             else
  121.                 for(j = 0; j < kScoreParts; j++)
  122.                     {
  123.                     thisError = NADisengageNoteChannel(g.na,d->noteChannel[j],true);
  124.                     ShowError(thisError);
  125.                     }
  126.             oldEngage = newEngage;
  127.             }
  128.  
  129.  
  130.         for(j = 0; j<kScoreParts; j++)
  131.             PlayScorePartBeat(&d->sr.score[j],d->noteChannel[j],beat);
  132.         Delay(6,&dummy);
  133.         }
  134.  
  135.     for(j = 0; j<kScoreParts; j++)
  136.         PlayScorePartBeat(&d->sr.score[j],d->noteChannel[j],kScoreLength);
  137.  
  138.     for(j = 0; j < kScoreParts; j++)
  139.         {
  140.         thisError = NAEngageNoteChannel(g.na,d->noteChannel[j]);
  141.         ShowError(thisError);
  142.         }
  143.  
  144.     }
  145.  
  146. short GetPipDuration(ScorePart *sp,short x,short y)
  147.     {
  148.     short d;
  149.  
  150.     d = x;
  151.     while(x < kScoreLength && GetPipBit(sp,x,y))
  152.         x++;
  153.     d = x - d;
  154.  
  155.     return d;
  156.     }
  157.  
  158.  
  159. void ScoreToQTScore(TDoc *d)
  160.     {
  161.     long i,x,y;
  162.     ScorePart *sp;
  163.     short lastGoodX;
  164.     long duration;
  165.     long time;
  166.     long deltaTime;
  167.     long *w;
  168.     long timeScalar;
  169.  
  170.     timeScalar = 1;
  171.  
  172.     if(d->qtScore)
  173.         DisposeHandle(d->qtScore);
  174.     d->qtScore = NewHandle(40000);
  175.     HLock(d->qtScore);
  176.     w = (void *)*d->qtScore;
  177.  
  178.     lastGoodX = 0;
  179.     for(x = 0; x < kScoreLength; x++)
  180.         {
  181.         for (i = 0; i < kScoreParts; i++)
  182.             {
  183.             sp = &d->sr.score[i];
  184.             for (y = 0; y < kScoreHeight; y++)
  185.                 {
  186.                 if(GetPipBit(sp,x,y)
  187.                         && (x == 0 || !GetPipBit(sp,x-1,y)))
  188.                     {
  189.                     if(x > lastGoodX)                    /* emit rest if necessary */
  190.                         {
  191.                         duration = timeScalar * (x - lastGoodX);
  192.                         *w++ = duration;
  193.                         lastGoodX = x;
  194.                         }
  195.  
  196.                     /*
  197.                      * emit note event
  198.                      */
  199.                     duration = timeScalar * GetPipDuration(sp,x,y);
  200.                     *w++ = 0x20000000 | (i << 24)
  201.                             | ((kNoteRangeHigh - y - 32) << 18)
  202.                             | (90L << 11)
  203.                             | duration;
  204.                     }
  205.                 }
  206.             }
  207.         }
  208.  
  209.     duration = timeScalar * (kScoreLength - lastGoodX);
  210.     if(duration)
  211.         *w++ = duration;
  212.     
  213.     *w++ = 0x60000000;
  214.     *w++ = -1;
  215.  
  216.     SetHandleSize(d->qtScore,((char *)w) - ((char *)*d->qtScore));
  217.  
  218.     d->validQTScore = true;
  219.     }
  220.  
  221.  
  222. void DelayXUnits(long x, long units)
  223.     {
  224.     long dummy;
  225.  
  226.     if(x < 0)
  227.         Debugger();
  228.  
  229.     Delay(x * 60 / units, & dummy);
  230.     }
  231.  
  232.  
  233. typedef enum
  234.     {
  235.     qNoteOff,
  236.     qSleep
  237.     } qCommand;
  238.  
  239.  
  240.     
  241.  
  242. void PlayQTScore(TDoc *d)
  243.     {
  244.     Handle qtScore;
  245.     long *qtScorePtr;
  246.     long *w;
  247.     unsigned short command;
  248.     unsigned long op1,op2,op3,op4;
  249.     EPQ *q;
  250.     EPQEvent e;
  251.     long timeNow;
  252.     long nextDelay;
  253.     ComponentResult thisError;
  254.  
  255.     unsigned short instrument,pitch,velocity;
  256.     long duration;
  257.     short controller,value;
  258.  
  259.     PrerollDoc(d);
  260.  
  261.     if(!d->validQTScore)
  262.         ScoreToQTScore(d);
  263.  
  264.     qtScore = d->qtScore;
  265.  
  266.     HLock(qtScore);
  267.     qtScorePtr = (void *)*qtScore;
  268.  
  269.     q = NewEPQ(2000);
  270.     w = qtScorePtr;
  271.     timeNow = 0;
  272.  
  273.  
  274.     while(1)
  275.         {
  276.         op1 = *w++;
  277.         if(op1 == 0xFFFFffff)
  278.             goto done;
  279.  
  280.         command = op1>>29;
  281.         if(command == 0)                /* rest */
  282.             {
  283.             e.time = timeNow + op1;
  284.             e.data1 = qSleep;
  285.             AddEventEPQ(q,&e);
  286.  
  287.             do
  288.                 {
  289.                 ExtractEventEPQ(q,&e);
  290.                 if(e.time != timeNow)
  291.                     DelayXUnits(e.time - timeNow,600);
  292.                 timeNow = e.time;
  293.                 if(e.data1 == qNoteOff)
  294.                     {
  295.                     thisError = NAPlayNote(g.na,d->noteChannel[e.data2],e.data3,0);
  296.                     ShowError(thisError);
  297.                     }
  298.                 } while(GetSizeEPQ(q) && e.data1 != qSleep);
  299.  
  300.             while(GetSizeEPQ(q) != 0 && PeekTopEPQ(q) == timeNow)
  301.                 {
  302.                 ExtractEventEPQ(q,&e);
  303.                 if(e.data1 == qNoteOff)
  304.                     {
  305.                     thisError = NAPlayNote(g.na,d->noteChannel[e.data2],e.data3,0);
  306.                     ShowError(thisError);
  307.                     }
  308.                 };
  309.             }
  310.  
  311.         else if (command == 1)
  312.             {
  313.             instrument = (op1 >> 24) & 31;
  314.             pitch = ((op1 >> 18) & 63) + 32;
  315.             velocity = (op1>>11) & 127;
  316.             duration = op1 & 0x03FF;
  317.  
  318.             thisError = NAPlayNote(g.na,d->noteChannel[instrument],pitch,velocity);
  319.             ShowError(thisError);
  320.  
  321.  
  322.             e.time = timeNow + duration;
  323.             e.data1 = qNoteOff;
  324.             e.data2 = instrument;
  325.             e.data3 = pitch;
  326.             AddEventEPQ(q,&e);
  327.             }
  328.         }
  329. done:
  330.     DisposeEPQ(q);
  331.  
  332.     }
  333.  
  334.